using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using AdminApiTemplate.Api.Enums;
using AdminApiTemplate.Cache;
using AdminApiTemplate.Common.Exceptions;
using AdminApiTemplate.Common.Helpers;
using AdminApiTemplate.Common.Models;
using System.Diagnostics;
using System.Text;

namespace AdminApiTemplate.Api.Helpers
{
    /// <summary>
    /// Web相关处理类
    /// </summary>
    public class WebHelper
    {
        private HttpContext _context;

        private object _requestModel;

        private bool _checkRequestModel;

        /// <summary>
        /// 构造函数（禁用无参数构造函数）
        /// </summary>
        private WebHelper()
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requestModel"></param>
        /// <param name="checkRequestModel"></param>
        public WebHelper(HttpContext context, object requestModel, bool checkRequestModel = true)
        {
            _context = context;
            _requestModel= requestModel;
            _checkRequestModel= checkRequestModel;
        }

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="userType"></param>
        /// <param name="userId"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public ActionResult Execute<T>(SysUserTypeEnum userType, string userId, Func<T> func)
        {
            var sw = new Stopwatch();
            sw.Start();

            var body = "";
            if (_context.Request.Body.CanRead)
            {
                _context.Request.Body.Position= 0;
                using (var reader = new StreamReader(_context.Request.Body))
                {
                    body = reader.ReadToEndAsync().Result;
                    _context.Request.Body.Position= 0;
                }
            }

            var requestId = RandomHelper.RequestId();
            var rsp = new ApiResponseBase<T>
            {
                ErrorCode = 999,
                ErrorMsg = "系统繁忙，请稍后再试",
                RequestId = requestId
            };

            var apiLog = new AddApiLogRequest
            {
                RequestId = requestId,
                HttpMethod = _context.Request.Method.ToUpper(),
                Url = _context.Request.Path,
                QueryString = _context.Request.QueryString.ToUriComponent(),
                Request = body,
                Success = false,
                UserAgent = _context.Request.Headers.UserAgent,
                IP = _context.Connection.RemoteIpAddress.MapToIPv4().ToString(),
                UserType = userType,
                UserId = userId
            };

            try
            {
                if (_checkRequestModel)
                {
                    if (_requestModel == null)
                    {
                        throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "参数无效");
                    }

                    var invalids = ValidationHelper.Validate(_requestModel);
                    if (invalids.Count>0)
                    {
                        throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, string.Join(",", invalids.Select(o => $"{o.Display}{o.Message}")), string.Join(",", invalids.Select(o => $"{o.Name}{o.Message}")));
                    }
                }

                var result = func.Invoke();
                rsp.Data = result;
                rsp.ErrorCode = null;
                rsp.ErrorMsg = null;
                rsp.ErrorMsg2 = null;
                apiLog.Success = true;
            }
            catch (WithCodeException wcex)
            {
                rsp.ErrorCode = wcex.Code;
                rsp.ErrorMsg = wcex.Message;
                rsp.ErrorMsg2 = wcex.Message2;
            }
            catch (Exception ex)
            {
                var wcex = ex.InnerException as WithCodeException;
                if (wcex != null)
                {
                    rsp.ErrorCode = wcex.Code;
                    rsp.ErrorMsg = wcex.Message;
                    rsp.ErrorMsg2 = wcex.Message2;
                }
                else
                {
                    apiLog.Error = ex.ToString();
                }
            }

            var json = JsonConvert.SerializeObject(rsp, CacheHelper.ExcludeNullJsonConfig);
            apiLog.Response = json;

            sw.Stop();
            apiLog.CostTime = sw.ElapsedMilliseconds;

            try
            {
                ApiLogHelper.WriteToFile(apiLog);
                ApiLogHelper.WriteToDb(apiLog);
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorAsync(ex.ToString());
            }

            return new ContentResult
            {
                Content = json,
                ContentType = "application/json",
                StatusCode = 200,
            };
        }

        /// <summary>
        /// 获取IP地址
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public static string GetIP(HttpContext context)
        {
            var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (!string.IsNullOrEmpty(ip))
            {
                return ip;
            }

            return context.Connection.RemoteIpAddress.MapToIPv4().ToString();
        }

        /// <summary>
        /// 获取网站配置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetWebsiteConfig(string key, string defaultValue = null)
        {
            var val = defaultValue;
            var fullName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", $"{key}.txt");
            if (File.Exists(fullName))
            {
                val = File.ReadAllText(fullName, Encoding.UTF8);
            }

            return val;
        }
    }
}
